<route lang="jsonc" type="page">
{
  "layout": "default",
  "style": {
    "navigationBarTitleText": ""
  }
}
</route>

<script lang="ts" setup>
import BoardCanvas from "./index.ts";
import ColorPicker from "@/components/ColorPicker/index.vue";
import LineWidth from "@/components/LineWidth/index.vue";

const props = defineProps({
  modelValue: {
    type: Boolean,
    required: true,
    default: false,
  },
});

const emit = defineEmits(["update:modelValue", "save"]);
const board = ref(null);
const drawBoard = ref(null);

const draw = reactive({
  canvas: null,
  ctx: null,
  startX: 0,
  stateY: 0,
  pathSegmentHistory: [],
  undoHistory: [],
  index: 0,
  lineColor: "#000",
  lineWidth: 2,
});

watch(
  () => draw.lineColor,
  (val) => {
    // draw.ctx.strokeStyle = draw.lineColor; // 设置线条颜色
    draw.ctx.setStrokeStyle(draw.lineColor);
  }
);

watch(
  () => draw.lineWidth,
  (val) => {
    // draw.ctx.lineWidth = draw.lineWidth; // 设置线条颜色
    draw.ctx.setLineWidth(draw.lineWidth);
  }
);
// 创建画布
const createCanvas = () => {
  const query = uni.createSelectorQuery().in(this);
  query
    .select("#drawCanvas")
    .fields({ node: true, size: true }, (res: UniApp.NodeInfo | UniApp.NodeInfo[]) => {
      const canvas = res.node;
      draw.canvas = canvas;
      draw.canvas.width = drawBoard.value.clientWidth;
      draw.canvas.height = drawBoard.value.clientHeight;
      // 绘制工具
      // draw.ctx = canvas.getContext("2d");
      draw.ctx = uni.createCanvasContext("drawCanvas", this);
      draw.ctx.setLineCap("round");
      draw.ctx.setStrokeStyle(draw.lineColor);
      draw.ctx.setLineWidth(draw.lineWidth);
      // 起始点位置
      draw.startX = 0;
      draw.stateY = 0;
      // 画布历史栈
      draw.pathSegmentHistory = [];
      draw.undoHistory = [];
      draw.index = 0;
      // 初始化
      init();
    })
    .exec();
  // const canvas = document.createElement("canvas");
  // canvas.width = drawBoard.value.clientWidth;
  // canvas.height = drawBoard.value.clientHeight;
  // canvas.style.display = "block";
  // drawBoard.value.appendChild(canvas);
  // return canvas;
};
const init = () => {
  // addPathSegment();
  setContext2DStyle();
  // 阻止默认右击事件
  draw.canvas.addEventListener("contextmenu", (e) => e.preventDefault());
  // 自定义鼠标按下事件
  // canvas.addEventListener("mousedown", mousedownEvent.bind(this));
  // draw.canvas.addEventListener("touchstart", touchstartEvent.bind(this));
  // 自定义键盘按下事件
  window.document.addEventListener("keydown", keydownEvent.bind(this));
};

const addPathSegment = () => {
  // const data = draw.ctx.getImageData(0, 0, draw.canvas.width, draw.canvas.height);
  const ctx = uni.createCanvasContext("#drawCanvas", this);
  // 在这里绘制一些内容，例如：
  // ctx.setFillStyle("red");
  // ctx.fillRect(10, 10, 150, 75);
  // 确保绘制完成
  ctx.draw(false, () => {
    // 使用setTimeout确保绘制完成后再获取数据（在某些情况下可能需要）
    setTimeout(() => {
      const canvasId = "drawCanvas";
      const x = 0;
      const y = 0;
      const width = draw.canvas.width;
      const height = draw.canvas.height;
      uni.canvasGetImageData(
        {
          canvasId,
          x,
          y,
          width,
          height,
          success: (res) => {
            const imageData = res.data;
            // 对 imageData 进行进一步处理，如分析颜色、保存到文件等
            // 删除当前索引后的路径片段，然后追加一个新的路径片段，更新索引
            draw.pathSegmentHistory.splice(draw.index + 1);
            draw.pathSegmentHistory.push(imageData);
            draw.undoHistory = [];
            draw.index = draw.pathSegmentHistory.length - 1;
          },
          fail: (err) => {
            console.error("获取 canvas 像素数据失败:", err.errMsg || "未知错误");
          },
        },
        this
      );
    }, 100); // 延迟确保渲染完成
  });
};
const setContext2DStyle = () => {
  draw.ctx.setLineCap("round");
  draw.ctx.setStrokeStyle(draw.lineColor);
  draw.ctx.setLineWidth(draw.lineWidth);
};
const touchstartEvent = (e) => {
  if (!isInit.value) return;
  e.stopPropagation();
  // const that = this;
  // const ctx = draw.ctx;
  // ctx.beginPath();
  // ctx.moveTo(e.touches[0].x, e.touches[0].y);
  // ctx.stroke();

  draw.undoHistory = [];
  draw.pathSegmentHistory.splice(draw.index + 1);
  draw.pathSegmentHistory.push({
    style: {
      color: draw.lineColor,
      width: draw.lineWidth,
    },
    coordinates: [
      {
        type: e.type,
        x: e.touches[0].pageX,
        y: e.touches[0].pageY,
      },
    ],
  });
  draw.index++;
  drawGraphics();
};

const touchmoveEvent = function (e) {
  if (!isInit.value) return;
  e.stopPropagation();
  // draw.ctx.lineTo(e.touches[0].x, e.touches[0].y);
  // draw.ctx.stroke();
  draw.undoHistory = [];
  draw.pathSegmentHistory.splice(draw.index + 1);
  draw.pathSegmentHistory[draw.pathSegmentHistory.length - 1].coordinates.push({
    type: e.type,
    x: e.touches[0].pageX,
    y: e.touches[0].pageY,
  });
  draw.index++;
  drawGraphics();
};
const touchedEvent = function (e) {
  if (!isInit.value) return;
  // addPathSegment();
};

const drawGraphics = () => {
  let historyLen = draw.pathSegmentHistory.length;
  if (!historyLen) return;
  let currentData = draw.pathSegmentHistory[historyLen - 1];
  let coordinates = currentData.coordinates;
  if (!coordinates.length) return;
  let startPoint, endPoint;
  if (coordinates.length < 2) {
    startPoint = coordinates[coordinates.length - 1];
    endPoint = {
      x: startPoint.x + 1,
      y: startPoint.y,
    };
  } else {
    startPoint = coordinates[coordinates.length - 2];
    endPoint = coordinates[coordinates.length - 1];
  }
  const ctx = uni.createCanvasContext("#drawCanvas", this);
  draw.ctx.beginPath();

  draw.ctx.setLineCap("round");
  draw.ctx.setStrokeStyle(draw.lineColor);
  draw.ctx.setLineWidth(draw.lineWidth);
  draw.ctx.moveTo(startPoint.x, startPoint.y);
  draw.ctx.lineTo(endPoint.x, endPoint.y);
  draw.ctx.stroke();
  draw.ctx.draw(true);
};

const keydownEvent = (e) => {
  if (!isInit.value) return;
  if (!e.ctrlKey) return;
  switch (e.keyCode) {
    case 90:
      undo();
      break;
    case 89:
      redo();
      break;
  }
};

const undo = () => {
  if (draw.index <= 0) return;
  draw.ctx.draw();
  draw.undoHistory.push(draw.pathSegmentHistory.pop());
  // draw.pathSegmentHistory.push(imageData);
  for (let index = 0; index < draw.index - 1; index++) {
    const item = draw.pathSegmentHistory[index];
    if (!item) {
      break;
    }
    let { color, width } = item.style;

    draw.ctx.setLineCap("round");
    draw.ctx.setStrokeStyle(color);
    draw.ctx.setLineWidth(width);

    if (item.coordinates.length >= 2) {
      item.coordinates.forEach((it) => {
        if (it.type == "touchstart") {
          draw.ctx.moveTo(it.x, it.y);
        } else {
          draw.ctx.lineTo(it.x, it.y);
        }
      });
    } else {
      const point = item.coordinates[0];
      draw.ctx.moveTo(point.x, point.y);
      draw.ctx.lineTo(point.x + 1, point.y);
    }
    draw.ctx.stroke();
    draw.ctx.draw(true);
  }
};
const redo = () => {
  if (draw.undoHistory.length <= 0) return;

  draw.pathSegmentHistory.push(draw.undoHistory.pop());

  draw.pathSegmentHistory.forEach((item, index) => {
    let { color, width } = item.style;

    draw.ctx.setLineCap("round");
    draw.ctx.setStrokeStyle(color);
    draw.ctx.setLineWidth(width);

    if (item.coordinates.length >= 2) {
      item.coordinates.forEach((it) => {
        if (it.type == "touchstart") {
          draw.ctx.moveTo(it.x, it.y);
        } else {
          draw.ctx.lineTo(it.x, it.y);
        }
      });
    } else {
      const point = item.coordinates[0];
      draw.ctx.moveTo(point.x, point.y);
      draw.ctx.lineTo(point.x + 1, point.y);
    }
    draw.ctx.stroke();
    draw.ctx.draw(true);
  });
};

const close = () => {
  isInit.value = false;
  setTimeout(() => {
    emit("update:modelValue", false);
  }, 500);
};

const isInit = ref(false);

watch(
  () => props.modelValue,
  (val) => {
    if (val) {
      // canvas画布

      // 在 DOM 更新后执行回调
      nextTick(() => {
        createCanvas();
        isInit.value = true;
      });
    } else {
      isInit.value = false;
    }
  },
  {
    immediate: true,
    deep: true,
  }
);

const saveImg = (e) => {
  uni.canvasToTempFilePath({
    x: 0,
    y: 0,
    width: draw.canvas.width,
    height: draw.canvas.height,
    destWidth: draw.canvas.width,
    destHeight: draw.canvas.height,
    canvasId: "drawCanvas",
    success: function (res) {
      // 在H5平台下，tempFilePath 为 base64
      emit("save", {
        img: res.tempFilePath,
        path: draw.pathSegmentHistory,
      });
      close();
    },
  });
};

const setHistoryPath = (arr) => {
  draw.pathSegmentHistory = [...arr];
  draw.index = arr.length - 1;
  draw.undoHistory = [];
  draw.ctx.draw();
  for (let index = 0; index <= draw.index; index++) {
    const item = draw.pathSegmentHistory[index];
    if (!item) {
      break;
    }
    let { color, width } = item.style;

    draw.ctx.setLineCap("round");
    draw.ctx.setStrokeStyle(color);
    draw.ctx.setLineWidth(width);

    if (item.coordinates.length >= 2) {
      item.coordinates.forEach((it) => {
        if (it.type == "touchstart") {
          draw.ctx.moveTo(it.x, it.y);
        } else {
          draw.ctx.lineTo(it.x, it.y);
        }
      });
    } else {
      const point = item.coordinates[0];
      draw.ctx.moveTo(point.x, point.y);
      draw.ctx.lineTo(point.x + 1, point.y);
    }
    draw.ctx.stroke();
    draw.ctx.draw(true);
  }
};

defineExpose({
  setHistoryPath,
});
onMounted(() => {
  // board.value = new BoardCanvas(drawBoard.value);
});
onBeforeUnmount(() => {
  window.document.removeEventListener("keydown", keydownEvent.bind(this));
});
</script>

<template>
  <view
    class="drawing-board w-[100vw] h-[100vh] absolute top-0 left-0"
    v-if="props.modelValue"
  >
    <view id="drawBoard" ref="drawBoard" style="width: 100%; height: 100%">
      <canvas
        canvas-id="drawCanvas"
        id="drawCanvas"
        ref="drawCanvas"
        class="w-full block"
        @touchstart.stop="touchstartEvent"
        @touchmove.stop="touchmoveEvent"
        @touchend.stop="touchedEvent"
      ></canvas>
    </view>
    <view
      class="i-carbon-close-outline w-[36px] h-[36px] absolute right-[16px] top-[16px] z-100"
      @click.stop="close"
    ></view>
    <view
      class="z-100 absolute left-0 w-[100vw] h-auto shadow-bg px-[12px] py-[12px] bg-white flex items-center flex-wrap gap-3 box-border"
      :class="isInit ? 'bottom-0' : 'bottom-[-100%]'"
    >
      <view class="w-full flex justify-between">
        <view class="flex items-center gap-1">
          <view
            class="w-[28px] h-[28px] i-carbon-undo"
            :class="draw.index === 0 ? 'text-[#939393]' : ''"
            @click="undo"
          ></view>
          <view
            class="w-[28px] h-[28px] i-carbon-redo"
            :class="draw.undoHistory.length == 0 ? 'text-[#939393]' : ''"
            @click="redo"
          ></view
        ></view>
        <view class="w-[28px] h-[28px] i-carbon-checkmark" @click="saveImg"></view>
      </view>
      <ColorPicker v-model="draw.lineColor" />
      <LineWidth v-model="draw.lineWidth" />
    </view>
    <!-- <view id="container" ref="container" style="width: 2000px; height: 2000px"></view> -->
  </view>
</template>

<style lang="scss" scoped>
.drawing-board {
  box-sizing: border-box;
  -moz-box-shadow: 0px -6px 12px #e9e9e9;
  -webkit-box-shadow: 0px -6px 12px #e9e9e9;
  box-shadow: 0px -6px 12px #e9e9e9;
  h3 {
    position: fixed;
    top: 30px;
    left: 50%;
    transform: translateX(-50%);
  }
}
.shadow-bg {
  -moz-box-shadow: 0px -6px 12px #e9e9e9;
  -webkit-box-shadow: 0px -6px 12px #e9e9e9;
  box-shadow: 0px -6px 12px #e9e9e9;
  transition: 0.5s;
}
#drawCanvas {
  height: calc(100% - 100px);
}
</style>
